// s.r(t), s.d(t, { default: () => MeshQueryModule })
import Logger from "../utils/Logger"
import Module from "./Module"
import RaycasterModule from "./RaycasterModule"
import RoomData from "../data/RoomData"
import FloorsData from "../data/FloorsData"

import * as THREE from "three"
import { roomFunc } from "../utils/room.util"
import EngineContext from "../EngineContext"
import Observable from "../observer/observable"
const u = new Logger("mesh-query-module")
const h = (...e) => {
  return t => {
    return e.every(e => e(t))
  }
}

export default class MeshQueryModule extends Module {
  raycaster: RaycasterModule
  floorData: FloorsData
  roomData: RoomData
  constructor() {
    super(...arguments)
    this.name = "mesh-query"
  }
  async init(e, t: EngineContext) {
    const [s, r, i] = await Promise.all([t.market.waitForData(FloorsData), t.market.waitForData(RoomData), t.getModule(RaycasterModule)])
    this.raycaster = i
    this.floorData = s
    this.roomData = r
  }
  nearestMeshInfoOnFloor(e, floorId: string) {
    const s = h(roomFunc.isRoomMesh, roomFunc.matchesFloorId(floorId))
    return this.raycaster.picking.nearest(new THREE.Vector3().set(e.x, e.y, e.z), s)
  }
  nearestMeshInfo(e) {
    return this.raycaster.picking.nearest(new THREE.Vector3().set(e.x, e.y, e.z), roomFunc.isRoomMesh)
  }
  inferMeshIdsFromPoint(e: any, point: THREE.Vector3) {
    const invalidRoomId = !e["roomId"] || !this.roomData.get(e["roomId"])
    const invalidFloorId = !e["floorId"] || !this.floorData.hasFloor(e["floorId"])
    if (invalidRoomId || invalidFloorId) {
      const i = invalidFloorId ? roomFunc.isRoomMesh : h(roomFunc.isRoomMesh, roomFunc.matchesFloorId(e["floorId"]))
      const a = this.raycaster.picking.nearest(new THREE.Vector3().set(point.x, point.y, point.z), i)
      a && roomFunc.isRoomMesh(a.object)
        ? (u.debug(
            "data-fixup:",
            invalidRoomId ? { roomId: a.object["roomId"], prev: e["roomId"] } : "",
            invalidFloorId ? { floorId: a.object["floorId"], prev: e["floorId"] } : "",
            {
              data: e
            }
          ),
          invalidRoomId && ((e["roomId"] = a.object["roomId"]), Observable.isObservable(e) && e.commit()),
          invalidFloorId && ((e["floorId"] = a.object["floorId"]), Observable.isObservable(e) && e.commit()))
        : u.warn("Nearest Room/Floor not found for:", {
            point,
            data: e,
            invalidRoomId,
            invalidFloorId
          })
    }
    return e
  }
}
